package org.particlethink.utils;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

public class ObjectUtils {

    public static <T> T instanceFromMap(Map<String, Object> map, Class<T> clazz)
            throws InstantiationException, IllegalAccessException {
        T t = clazz.newInstance();

        for (Field field : clazz.getDeclaredFields()) {
            field.setAccessible(true);
            String fieldName = field.getName();
            if (map.containsKey(fieldName)) {
                Object value = map.get(fieldName);
                Class<?> fieldType = field.getType();
                Object typedValue;

                // 若字段是集合类型且其值非空
                if (Collection.class.isAssignableFrom(fieldType) && value instanceof Collection) {
                    Collection<?> collectionValue = (Collection<?>) value;
                    ParameterizedType collectionType = (ParameterizedType) field.getGenericType();
                    Class<?> collectionItemClazz = (Class<?>) collectionType.getActualTypeArguments()[0];

                    Collection<Object> newCollection = new ArrayList<>();
                    for (Object item : collectionValue) {
                        // 若集合内存储的是非基础类型，则需递归进行映射
                        if (Map.class.isAssignableFrom(item.getClass())) {
                            newCollection.add(instanceFromMap((Map) item, collectionItemClazz));
                        } else {
                            newCollection.add(item);
                        }
                    }
                    typedValue = newCollection;
                }
                // 若字段是非基础类型
                else if (!isPrimitiveOrWrapper(fieldType) && value instanceof Map) {
                    typedValue = instanceFromMap((Map) value, fieldType);
                }
                // 若字段是基础类型
                else {
                    typedValue = value;
                }

                try {
                    field.set(t, typedValue);
                } catch (IllegalAccessException e) {
                    throw new RuntimeException(e);
                }
            }
        }
        return t;
    }

    // 判断是否为基础类型或其包装器类型
    private static boolean isPrimitiveOrWrapper(Class<?> type) {
        return (type.isPrimitive() && type != void.class)
                || type == Double.class
                || type == Float.class
                || type == Long.class
                || type == Integer.class
                || type == Short.class
                || type == Character.class
                || type == Byte.class
                || type == Boolean.class;
    }


    public static <T> Map<String, Object> mapFromInstance(T t, Class<T> clazz) throws IllegalAccessException {
        Map<String, Object> map = new HashMap<>();
        for (Field field : clazz.getDeclaredFields()) {
            field.setAccessible(true);
            map.put(field.getName(), field.get(t));
        }
        return map;
    }

    public static <T> boolean isEmpty(T[] array) {
        return array == null || array.length == 0;
    }

    public static <T> boolean isEmpty(Collection<T> collection) {
        return collection == null || collection.isEmpty();
    }

    public static boolean isEmpty(String string) {
        return string == null || string.isEmpty();
    }

    public static boolean isEmpty(Integer integer) {
        return integer == null || integer == 0;
    }

    public static boolean isEmpty(Object object) {
        return object == null;
    }
}
